﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WS.EKA.ServiceInterface;
using WS.EKA.Model;
using WS.EKA.DataAccess;
using System.Threading.Tasks;
using WS.EKA.Utilities;
using WS.EKA.Utilities.Consts;
using System.Data.SqlClient;
using System.Xml.Serialization;
using System.Configuration;

namespace WS.EKA.ServiceImpl
{
    public class OrderService : IOrder
    {
        public List<Model.Order> GetOrderByMember(string loginId)
        {
            List<Order> list = OrderContext.GetByConditions(t => t.MemLoginID == loginId).OrderByDescending(x=>x.CreateTime).ToList();

            foreach (var order in list)
            {
                Guid orderId = order.Guid;
                order.ProductList = OrderProductContext.GetProductByOrderId(orderId);
            }
            return list;
        }

        public Order GetOrderByCode(string orderCode)
        {
            Order order=OrderContext.Get(t => t.OrderNumber == orderCode);
            if (order != null)
            {
                order.Payment = PaymentContext.Get(order.PaymentGuid);
                order.DispatchMode = DispatchModeContext.Get(order.DispatchModeGuid);
                order.ProductList = OrderProductContext.GetProductByOrderId(order.Guid);
            }
            return order;
        }

        public void Add(Order order)
        {
            CaculatePrice(order);
            OrderContext.Save(order);
        }

        public void Update(Order order)
        {
            if (order.Guid == null)
                throw new KeyNotFoundException("Order 主键不能为空");
            OrderContext.Save(order);
        }

        #region
        //配送价格
        public decimal GetDispatchPrice(Order order)
        {
            bool userFormula = true;
            decimal noUseDispatchPrice = 0;
            decimal dispatchPrice = 0;

            DispatcherMode dispatcherMode = null;
            dynamic dispatchItemRegions = null;

            Task getDispatcherMode = Task.Factory.StartNew(() =>
            {
                dispatcherMode = DispatcherModeContext.Get(x => x.Guid == order.DispatchModeGuid);
                //全国
                if (dispatcherMode.DispatchType == 0)
                    dispatchItemRegions = DispatchItemContext.GetByConditions(x => x.DispatchMode == order.DispatchModeGuid);
                else
                    dispatchItemRegions = DispatchItemRegionContext.GetByConditions(x => x.DispatchMode == order.DispatchModeGuid && x.Code.Contains(order.RegionCode));
            });

            Task.WaitAll(getDispatcherMode);

            List<Product> productList = CacheManager.Instance.GetObjectFromMemoryCache(CacheKey.Product) as List<Product>;
            var query = from a in order.ProductList
                        join b in productList on a.ProductGuid equals b.Guid
                        select a.BuyNumber * b.Weight;

            decimal totalWeight = query.ToList<decimal>().Sum();
            //order.ProductList.ForEach(x => totalWeight += x.Weight * x.BuyNumber);

            foreach (var dispatcherRegion in dispatchItemRegions)
            {
                if (dispatcherRegion.ItemCode == "Q")
                {
                    if (dispatcherRegion.ItemValue >= totalWeight)
                    {
                        userFormula = false;
                    }
                }
                if (dispatcherRegion.ItemCode == "P")
                {
                    //不使用公式时候的配送费用
                    noUseDispatchPrice = dispatcherRegion.ItemValue;
                }
            }

            if (userFormula)
            {
                string strFormula = dispatcherMode.Formula;
                foreach (var dispatcherRegion in dispatchItemRegions)
                {
                    strFormula = strFormula.Replace(dispatcherRegion.ItemCode, dispatcherRegion.ItemValue.ToString());
                }

                //计算商品的总重量
                //商品的总重量（替换到w中,都是以克计算）
                strFormula = strFormula.Replace("W", totalWeight.ToString());
                dispatchPrice = ComputeDispatchPrice(strFormula);
            }
            else
            {
                dispatchPrice = noUseDispatchPrice;
            }
            return dispatchPrice;
        }

        //保价费用
        public decimal GetInsurePrice(Order order)
        {
            return DispatcherModeContext.Get(x => x.Guid == order.DispatchModeGuid).SafeCost;
        }
        /// <summary>
        /// 抵用余额
        /// 需要注意抵用余额 消费券 消费积分大于总金额的情况
        /// </summary>
        /// <param name="memLoginID"></param>
        /// <returns></returns>
        public decimal GetAdvancePayment(string memLoginID)
        {
            string sql = "SELECT AdvancePayment FROM ShopNum1_Member WHERE MemLoginID=@MemLoginID";
            SqlParameter parameter = new SqlParameter("MemLoginID", memLoginID);
            return OrderContext.Exec3SQL<decimal>(sql, parameter).FirstOrDefault();
        }

        //包装费用
        public decimal GetPackFee(Guid packGuid, decimal totalPrice)
        {
            var packs = CacheManager.Instance.GetObjectFromMemoryCache(CacheKey.Pack) as List<Pack>;
            //Pack pack = packs.First(x => x.Guid == packGuid);
            Pack pack = (from p in packs
                         where p.Guid == packGuid
                         select p).FirstOrDefault();
            if (pack == null)
                return 0;
            if (totalPrice > pack.FreeLimit)
                return 0;
            else
                return pack.Cost;
        }

        //贺卡费用
        public decimal GetBlessCardFee(Guid blessCardGuid, decimal totalPrice)
        {
            var blessCards = CacheManager.Instance.GetObjectFromMemoryCache(CacheKey.BlessCard) as List<BlessCard>;
            var blessCard = (from p in blessCards
                             where p.Guid == blessCardGuid
                             select p).FirstOrDefault();
            if (blessCard == null)
                return 0;
            if (totalPrice > blessCard.FreeLimit)
                return 0;
            else
                return blessCard.Cost;
        }

        /// <summary>
        /// 抵用消费券
        /// 在接最后付款的时候需要将消费券的使用次数减一
        /// </summary>
        /// <param name="order"></param>
        /// <returns></returns>
        public decimal GetFavourTicket(Order order)
        {
            var favourTicket = MemberFavourTicketContext.Get(x => x.MemLoginID == order.MemLoginID
                && x.FavourTicketCode == order.UsedFavourTicket);
            if (favourTicket == null)
                return 0;
            if (favourTicket.EndDate < DateTime.Now || favourTicket.StartDate > DateTime.Now)
            {
                return 0;
            }
            if (favourTicket.LimitTimes < 1)
            {
                return 0;
            }
            var orderProducts = order.ProductList;
            decimal totalProductPrice = 0;
            orderProducts.ForEach(x => totalProductPrice += (x.BuyNumber * x.BuyPrice));
            if (totalProductPrice < favourTicket.MinimalCost)
            {
                return 0;
            }
            return favourTicket.FaceValue;
        }

        #region 积分

        public decimal GetScores(Order order)
        {
            decimal CanUsedScore = 0;
            List<OrderProduct> orders = order.ProductList;
            var account = AccountContext.Get(x => x.MemLoginID == order.MemLoginID);
            if (account.Score <= 0)
            {
                return 0;
            }
            ShopSetting setting = ShopSetting.GetInstance();
            foreach (OrderProduct orderProduct in order.ProductList)
            {
                //计算每种商品的折扣价格
                decimal yourPrice = GetMemberRankPrice(order.MemLoginID, orderProduct.ProductGuid, orderProduct.BuyPrice);
                Product p = ProductContext.Get(x => x.Guid == orderProduct.ProductGuid);
                if (p.SocreIntegral == -1)
                    CanUsedScore += yourPrice * setting.ScorePaymentProportion * setting.ScoreConversionProportion;
                else
                    CanUsedScore += p.SocreIntegral * setting.ScoreConversionProportion;
            }
            if (account.Score < CanUsedScore)
                CanUsedScore = account.Score;
            order.UseScore = Convert.ToInt32(CanUsedScore);
            return CanUsedScore / setting.ScoreConversionProportion;
        }

        /// <summary>
        /// 取登录后的会员的会员价格
        /// </summary>
        /// <returns></returns>
        private decimal GetMemberRankPrice(string memLoginID, Guid productID, decimal shopPrice)
        {
            //如果是登录的用户，需要计算会员的等级价格
            Account account = AccountContext.Get(x => x.MemLoginID == memLoginID);

            //根据会员等级guid和商品的guid取当前会员的对应的该商品的价格
            ProductMemberRankPrice memberRankPrice = ProductMemberRankPriceContext
                .Get(x => x.MemberRankGuid == account.MemberRankGuid && x.ProductGuid == productID);

            if (memberRankPrice != null)
            {
                //如果表中存在记录，表明添加商品的时候填写了会员价格 
                return memberRankPrice.Price;
            }
            else
            {
                //如果表不存在记录，表明添加商品的时候填没有填写会员价格
                //会员的价格需要通过会员等级的折扣比例来计算
                //1，取会员等级的折扣
                decimal discount = MemberRankContext.Get(account.MemberRankGuid).Discount;

                //3,当前会员等级的价格计算=本店售价*会员等级的折扣 
                decimal yourPrice = (discount * shopPrice) / 10;

                return decimal.Round(yourPrice, 2);
            }
        }

        #endregion

        //发票税
        public decimal GetTax(Order order, decimal allProductPrice)
        {
            decimal InvoiceTaxValue = 0;
            var settings = ShopSetting.GetInstance();
            //是否需要发票
            if (!settings.IsInvoice)
            {
                InvoiceTaxValue = 0;
            }
            else
            {
                if (string.IsNullOrEmpty(order.InvoiceType))
                {
                    InvoiceTaxValue = 0;
                }
                //计算发票
                else
                {
                    decimal taxRate = 0;
                    if (settings.InvoiceType.InvoiceType1.Contains(order.InvoiceType))
                    {
                        taxRate = Convert.ToDecimal(settings.InvoiceType.InvoiceType1.Split('|')[1]);
                    }
                    else if (settings.InvoiceType.InvoiceType2.Contains(order.InvoiceType))
                    {
                        taxRate = Convert.ToDecimal(settings.InvoiceType.InvoiceType2.Split('|')[1]);
                    }
                    else
                    {
                        taxRate = Convert.ToDecimal(settings.InvoiceType.InvoiceType3.Split('|')[1]);
                    }
                    InvoiceTaxValue = allProductPrice * (taxRate / 100);
                }
            }
            return InvoiceTaxValue;
        }

        //支付费
        public decimal GetPayment(Guid paymentGuid, decimal allProductPrice)
        {
            decimal PaymentPrice = 0;
            Payment payment = PaymentContext.Get(paymentGuid);
            if (payment.IsPercent == 0)
            {
                PaymentPrice = payment.Charge;
            }
            else
            {
                PaymentPrice = allProductPrice * payment.Charge / 100;
            }
            return PaymentPrice;
        }

        //促销
        private decimal GetPromotion(Guid activityGuid, decimal Dispatcher, decimal PaymentPrice, decimal allProductPrice)
        {
            decimal DiscountValue = 0;
            SalesPromotion promotion = SalesPromotionContext.Get(activityGuid);
            if (promotion == null)
                return 0;
            if (promotion.PromotionType == "FullAndFree_Operate.aspx")
            {
                FullAndFree fillAndFree = FullAndFreeContext.Get(activityGuid);
                if (fillAndFree.FreeItem == 0)
                    //免配送费
                    DiscountValue = Dispatcher;
                if (fillAndFree.FreeItem == 1)
                    DiscountValue = PaymentPrice;
            }
            if (promotion.PromotionType == "FullAndDiscount_Operate.aspx")
            {
                FullAndDiscount fullAndDiscount = FullAndDiscountContext.Get(activityGuid);
                if (fullAndDiscount.DiscountMode == 0)
                    DiscountValue = fullAndDiscount.Number / 100 * allProductPrice;
                if (fullAndDiscount.DiscountMode == 1)
                    DiscountValue = fullAndDiscount.Number;
            }
            return DiscountValue;
        }

        private decimal ComputeDispatchPrice(string formula)
        {
            try
            {
                string strSql = "SELECT " + formula + " AS DispatchPrice";
                var result = OrderContext.Exec3SQL<decimal>(strSql);
                return result.First();
            }
            catch
            {
                return 0;
            }
        }
        #endregion

        public Order CaculatePrice(Order order)
        {
            //预存款
            decimal AdvancePayment = 0;
            //促销优惠
            decimal PromotionPrice = 0;
            //积分
            decimal ScorePrice = 0;
            //优惠券
            decimal FavouriteTicket = 0;
            //优惠
            decimal DiscountValue = 0;
            //发票税
            decimal InvoiceTaxValue = 0;
            //支付手续费
            decimal PaymentPrice = 0;
            //包装费用
            decimal PackPrice = 0;
            //贺卡费用
            decimal BlessCard = 0;
            //配送费
            decimal Dispatcher = 0;
            //保价费用
            decimal InsurePrice = 0;
            //订单最终金额
            decimal orderPrice = 0;
            //应付款金额
            decimal finallyPay = 0;
            //商品总金额
            decimal allProductPrice = 0;
            foreach (OrderProduct orderProduct in order.ProductList)
            {
                allProductPrice += orderProduct.BuyPrice * orderProduct.BuyNumber;
            }

            #region dispatch

            var dispatchTask = Task.Factory.StartNew(() =>
            {
                Dispatcher = GetDispatchPrice(order);
            });
            #endregion

            #region InsurePrice

            var insurePriceTask = Task.Factory.StartNew(() =>
            {
                InsurePrice = GetInsurePrice(order);
            });

            #endregion

            #region FavourTicket

            var favourTicketTask = Task.Factory.StartNew(() =>
            {
                FavouriteTicket = GetFavourTicket(order);
            });

            #endregion

            #region Tax

            var taxTask = Task.Factory.StartNew(() =>
            {
                InvoiceTaxValue = GetTax(order, allProductPrice);
            });

            #endregion

            #region payment

            var paymentTask = Task.Factory.StartNew(() =>
            {
                PaymentPrice = GetPayment(order.PaymentGuid, allProductPrice);
            });

            #endregion

            Task.WaitAll(dispatchTask, insurePriceTask, favourTicketTask, taxTask, paymentTask);

            #region pack

            PackPrice = GetPackFee(order.PackGuid, allProductPrice);

            #endregion

            #region blessCard

            BlessCard = GetBlessCardFee(order.BlessCardGuid, allProductPrice);

            #endregion

            #region promotion

            var promotionTask = Task.Factory.StartNew(() =>
            {
                PromotionPrice = GetPromotion(order.ActivityGuid, Dispatcher, PaymentPrice, allProductPrice);
            });

            #endregion

            #region score

            var scoreTask = Task.Factory.StartNew(() =>
            {
                ScorePrice = GetScores(order);
            });

            #endregion

            #region advancePayment

            var advancePaymentTask = Task.Factory.StartNew(() =>
            {
                AdvancePayment = GetAdvancePayment(order.MemLoginID);
            });

            #endregion

            Task.WaitAll(promotionTask, scoreTask, advancePaymentTask);

            orderPrice = allProductPrice - DiscountValue + InvoiceTaxValue + Dispatcher
                + InsurePrice + PaymentPrice + PackPrice + BlessCard;

            finallyPay = orderPrice;
            //使用优惠券
            if (order.ActivityGuid != null)
            {
                finallyPay -= FavouriteTicket;
            }
            finallyPay -= ScorePrice;

            decimal usedAdvancePayment = 0;
            if (AdvancePayment >= finallyPay)
            {
                usedAdvancePayment = finallyPay;
                //余额充足
                finallyPay = 0;
            }
            else
            {
                usedAdvancePayment = AdvancePayment;
                finallyPay -= AdvancePayment;
            }

            order.ProductPrice = allProductPrice;
            order.DispatchPrice = Dispatcher;
            order.InsurePrice = InsurePrice;

            order.PaymentPrice = PaymentPrice;
            order.PackPrice = PackPrice;
            order.BlessCardPrice = BlessCard;
            order.SurplusPrice = usedAdvancePayment;
            order.Discount = DiscountValue;
            order.ShouldPayPrice = finallyPay;
            order.ScorePrice = ScorePrice;
            order.InvoiceTax = InvoiceTaxValue;
            order.ActvieContent = FavouriteTicket.ToString();
            return order;

        }

        public List<string> GetInvoiceTaxType()
        {
            List<string> invoiceTypes = new List<string>();
            var settings = ShopSetting.GetInstance();
            invoiceTypes.Add(settings.InvoiceType.InvoiceType1);
            invoiceTypes.Add(settings.InvoiceType.InvoiceType2);
            invoiceTypes.Add(settings.InvoiceType.InvoiceType3);
            return invoiceTypes;
        }
    }

    #region Settings
    [Serializable]
    [XmlRoot]
    public class ShopSetting
    {
        public int ScoreConversionProportion { get; set; }
        public int ScorePaymentProportion { get; set; }
        public InvoiceType InvoiceType { get; set; }
        public bool IsInvoice { get; set; }

        public static ShopSetting GetInstance()
        {
            string filePath = AppDomain.CurrentDomain.BaseDirectory + ConfigurationManager.AppSettings["ShopSetting"];
            return XmlSerlizer.Deserialize<ShopSetting>(filePath);
        }
    }
    [Serializable]
    [XmlRoot]
    public class InvoiceType
    {
        public string InvoiceType1 { get; set; }
        public string InvoiceType2 { get; set; }
        public string InvoiceType3 { get; set; }
    }
    #endregion
}
